home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dr. Windows 3
/
dr win3.zip
/
dr win3
/
PROGRAMR
/
OLE2BOOK.ZIP
/
CHAP06.ZIP
/
CHAP06
/
FREELOAD
/
DOCUMENT.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-21
|
17KB
|
658 lines
/*
* DOCUMENT.CPP
*
* Implementation of the CFreeloaderDoc derivation of CDocument.
* We create a default handler object and use it for drawing, data
* caching, and serialization.
*
* Copyright (c)1993 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Software Design Engineer
* Microsoft Systems Developer Relations
*
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#include "freeload.h"
/*
* CFreeloaderDoc::CFreeloaderDoc
* CFreeloaderDoc::~CFreeloaderDoc
*
* Constructor Parameters:
* hInst HINSTANCE of the application.
*/
CFreeloaderDoc::CFreeloaderDoc(HINSTANCE hInst)
: CDocument(hInst)
{
m_pIStorage=NULL;
m_pIUnknown=NULL;
m_dwConn=0;
return;
}
CFreeloaderDoc::~CFreeloaderDoc(void)
{
ReleaseObject();
if (NULL!=m_pIStorage)
m_pIStorage->Release();
return;
}
/*
* CFreeloaderDoc::ReleaseObject
*
* Purpose:
* Centralizes cleanup code for the object and its cache.
*
* Parameters:
* None
*
* Return Value:
* None
*/
void CFreeloaderDoc::ReleaseObject(void)
{
LPOLECACHE pIOleCache;
HRESULT hr;
if (0!=m_dwConn)
{
hr=m_pIUnknown->QueryInterface(IID_IOleCache
, (LPVOID FAR *)&pIOleCache);
if (SUCCEEDED(hr))
{
pIOleCache->Uncache(m_dwConn);
pIOleCache->Release();
}
}
if (NULL!=m_pIUnknown)
m_pIUnknown->Release();
CoFreeUnusedLibraries();
m_dwConn=0;
m_pIUnknown=NULL;
return;
}
/*
* CFreeloaderDoc::FMessageHook
*
* Purpose:
* Processes WM_PAINT for the document so we can draw the object.
*
* Parameters:
* <WndProc Parameters>
* pLRes LRESULT FAR * in which to store the return value
* for the message.
*
* Return Value:
* BOOL TRUE to prevent further processing, FALSE otherwise.
*/
BOOL CFreeloaderDoc::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
, LPARAM lParam, LRESULT FAR *pLRes)
{
PAINTSTRUCT ps;
HDC hDC;
RECT rc;
RECTL rcl;
LPVIEWOBJECT pIViewObject;
HRESULT hr;
if (WM_PAINT!=iMsg)
return FALSE;
hDC=BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rc);
/*
* To draw the object we can either QueryInterface for an IViewObject,
* call IViewObject::Draw, and IViewObject::Release, or we can use
* OleDraw which does exactly the same three steps, only calling
* ::Draw with defaults. OleDraw does exactly what is done here.
*/
if (NULL!=m_pIUnknown)
{
hr=m_pIUnknown->QueryInterface(IID_IViewObject
, (LPVOID FAR *)&pIViewObject);
if (SUCCEEDED(hr))
{
#ifndef WIN32
rcl.left =MAKELONG(rc.left, 0);
rcl.right =MAKELONG(rc.right, 0);
rcl.top =MAKELONG(rc.top, 0);
rcl.bottom=MAKELONG(rc.bottom, 0);
#else
//Win32 rectangles are already LONGs.
rcl=rc;
#endif
pIViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, 0, hDC
, &rcl, NULL, NULL, 0);
pIViewObject->Release();
}
}
EndPaint(hWnd, &ps);
return FALSE;
}
/*
* CFreeloaderDoc::ULoad
*
* Purpose:
* Loads a given document without any user interface overwriting the
* previous contents of the Polyline window. We do this by opening
* the file and telling the Polyline to load itself from that file.
*
* Parameters:
* fChangeFile BOOL indicating if we're to update the window title
* and the filename from using this file.
* pszFile LPSTR to the filename to load, NULL if the file is
* new and untitled.
*
* Return Value:
* UINT An error value from DOCERR_*
*/
UINT CFreeloaderDoc::ULoad(BOOL fChangeFile, LPSTR pszFile)
{
HRESULT hr;
CLSID clsID;
LPSTORAGE pIStorage;
LPUNKNOWN pIUnknown;
LPPERSISTSTORAGE pIPersistStorage;
DWORD dwMode=STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
if (NULL==pszFile)
{
//Create a new temp file.
hr=StgCreateDocfile(NULL, dwMode | STGM_CREATE | STGM_DELETEONRELEASE
, 0, &pIStorage);
if (FAILED(hr))
return DOCERR_COULDNOTOPEN;
m_pIStorage=pIStorage;
FDirtySet(FALSE);
Rename(NULL);
return DOCERR_NONE;
}
//Attempt to open the storage.
hr=StgOpenStorage(pszFile, NULL, dwMode, NULL, 0, &pIStorage);
if (FAILED(hr))
return DOCERR_COULDNOTOPEN;
/*
* When we previously called IPersistStorage::Save, OLE2.DLL kindly
* placed a CLSID into the IStorage for us, either CLSID_StaticMetafile,
* known to us as CLSID_FreeMetafile, or CLSID_StaticDib, known to us
* as CLSID_FreeDib. All we have to do is load this CLSID,
* create the object for that ID (using CoCreateInstance, see ::FPaste
* below).
*/
hr=ReadClassStg(pIStorage, &clsID);
//See if we know about it.
if (FAILED(hr) || !(IsEqualCLSID(clsID, CLSID_FreeMetafile)
|| IsEqualCLSID(clsID, CLSID_FreeDib)))
{
pIStorage->Release();
return DOCERR_READFAILURE;
}
//Go create an object, then tell *it* to load the data.
hr=CoCreateInstance(clsID, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown
, (LPVOID FAR *)&pIUnknown);
if (FAILED(hr))
{
pIStorage->Release();
return DOCERR_READFAILURE;
}
//Get IPersistStorage for the data we hold.
pIUnknown->QueryInterface(IID_IPersistStorage, (LPVOID FAR *)&pIPersistStorage);
hr=pIPersistStorage->Load(pIStorage);
pIPersistStorage->Release();
if (FAILED(hr))
{
pIUnknown->Release();
pIStorage->Release();
return DOCERR_READFAILURE;
}
m_pIStorage=pIStorage;
m_pIUnknown=pIUnknown;
Rename(pszFile);
FDirtySet(FALSE);
return DOCERR_NONE;
}
/*
* CFreeloaderDoc::USave
*
* Purpose:
* Writes the file to a known filename, requiring that the user has
* previously used FileOpen or FileSaveAs in order to have a filename.
*
* Parameters:
* uType UINT indicating the type of file the user requested
* to save in the File Save As dialog.
* pszFile LPSTR under which to save. If NULL, use the current name.
*
* Return Value:
* UINT An error value from DOCERR_*
*/
UINT CFreeloaderDoc::USave(UINT uType, LPSTR pszFile)
{
HRESULT hr;
LPSTORAGE pIStorage;
LPPERSISTSTORAGE pIPersistStorage;
CLSID clsID;
//If we have no data object, there's nothing to save.
if (NULL==m_pIUnknown)
return DOCERR_WRITEFAILURE;
//Get IPersistStorage for the data we hold.
hr=m_pIUnknown->QueryInterface(IID_IPersistStorage, (LPVOID FAR *)&pIPersistStorage);
if (FAILED(hr))
return DOCERR_WRITEFAILURE;
//Save or Save As with the same file is just a commit.
if (NULL==pszFile || (NULL!=pszFile && 0==lstrcmpi(pszFile, m_szFile)))
{
pIPersistStorage->Save(m_pIStorage, TRUE);
m_pIStorage->Commit(STGC_ONLYIFCURRENT);
pIPersistStorage->SaveCompleted(m_pIStorage);
pIPersistStorage->Release();
FDirtySet(FALSE);
return DOCERR_NONE;
}
/*
* When we're given a name, open the storage, creating it new if
* it does not exist or overwriting the old one. Then ::CopyTo
* from the current to the new, ::Commit the new, then ::Release
* the old.